#!/usr/bin/python
# -- coding:utf8 --

# 线上部署代码
import os
import sys

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# import util_log as utils
from app.model_phl.utils import select_sql_mysql_v1
from app.model_phl.v4.my_tool_package import get_is_none

import requests
import pandas as pd
import numpy as np
import json
import re
import warnings

warnings.filterwarnings("ignore")

# file_path_name = './model/applist_type_dict.json'
# current_path = os.path.dirname(__file__)

# file_path_name1 = file_path_name.replace("./", current_path + "/")
# with open(file_path_name1, 'r') as f:
#     app_type_dict = json.loads(f.read())


def get_list_value_is_in_str(match_list, params_str):
    for v in match_list:
        if type(v) == list:
            flg = 1
            for v_ in v:
                if str(v_).strip().lower() not in str(params_str).strip().lower():
                    flg = 0
            if flg == 1:
                return 1
        else:
            if str(v).strip().lower() in str(params_str).strip().lower():
                return 1
    return 0


def get_label_content(x, key_dict, cal_list):
    label_list = ['All']
    for key in cal_list:
        if key == 'All':
            continue
        else:
            match_list = key_dict[key]
            if get_list_value_is_in_str(match_list, x) == 1:
                label_list.append(key)
    return list(set(label_list))


def get_cal_division(numerator, denominator):
    try:
        if denominator == 0:
            return -999978
        elif get_is_none(numerator) or get_is_none(denominator):
            return -999977
        else:
            return round(numerator / denominator, 2)
    except Exception as e:
        return -999976


def get_app_df(ApplyNO):
    # 第一步：获取URL链接
    file_url_sql = """
    select 
    ApplyNO
    ,FileUrl
    from BindingFileUrl
    where ApplyNO = '{}'
    """.format(ApplyNO)
    url_df = select_sql_mysql_v1(file_url_sql)

    # 第二步：获取数据集
    response = requests.get(url_df['FileUrl'][0])
    if response.status_code == 200:
        json_data = response.json()
    else:
        print(f"Failed to download {url_df['FileUrl'][0]}, status code: {response.status_code}")

    # 第三步：解析sms数据
    json_data1 = eval(json_data)
    try:
        # 第四步：APP数据框
        app_df = pd.DataFrame(json.loads(json_data1['apps']))
        app_df['ApplyNO'] = ApplyNO
    except Exception as e:
        print(f"请求失败，错误信息: {str(e)}")

    # 第四步：获取申请时间
    apply_date_sql = """
        select 
        ApplyNO
        ,ApplyDate
        from SysJkApply
        where ApplyNO = '{}'
        """.format(ApplyNO)
    applydate_df = select_sql_mysql_v1(apply_date_sql)

    # 第五步：数据合并
    app_df = app_df.merge(applydate_df)

    return app_df


def get_format_data(df):
    try:
        file_path_name = './model/applist_type_dict.json'
        current_path = os.path.dirname(__file__)

        file_path_name1 = file_path_name.replace("./", current_path + "/")
        with open(file_path_name1, 'r') as f:
            app_type_dict = json.loads(f.read())
        
        # df = get_app_df(ApplyNO)
        if df.empty:
            return pd.DataFrame()
        df['InstallInterval'] = (
                pd.to_datetime(df['ApplyDate']) - pd.to_datetime(df['firstInstallTime'])).dt.total_seconds()
        df['InstallDays'] = df['firstInstallTime'].apply(lambda x: str(x).split()[0])
        df.loc[:, 'IsSystem'] = df['is_system'].apply(lambda x: 0 if x == 0 else 1)
        df.rename(columns={'appName': 'AppName', 'packageName': 'PackageName'}, inplace=True)
        app_key_list = ['All', 'Loan', 'bad1', 'bad2', 'good1', 'good2', 'FuzzyLoan', 'Normal', 'Casino']
        df['conLabel_1'] = df['AppName'].apply(lambda x: get_label_content(x, app_type_dict, app_key_list))
        df['conLabel_2'] = df['PackageName'].apply(lambda x: get_label_content(x, app_type_dict, app_key_list))

        # 标签集成
        df['conLabel'] = df[['conLabel_1', 'conLabel_2']].apply(
            lambda x: list(set(set(x['conLabel_1']) | set(x['conLabel_2']))), axis=1)
        cal_field_list = ['AppName', 'InstallInterval', 'InstallDays']
        for cal_field in cal_field_list:
            df[cal_field] = df[cal_field].apply(lambda x: np.nan if get_is_none(x) == True else x)
        return df
    except Exception as e:
        # utils.get_logger().error(e)
        print(f"错误信息: {str(e)}")
        return pd.DataFrame()


def get_windows_aggregation_main(df, con, dt, con_key, cal_field, cal_type, condition_dict_all, dt_dict):
    """
    统计聚合函数
    :param df:
    :param con:
    :param dt:
    :param con_key:
    :param cal_field:
    :param cal_type:
    :param condition_dict_all:
    :param dt_dict:
    :return:
    """
    df_tmp = df.copy()
    df_tmp[cal_field] = df_tmp[cal_field].apply(lambda x: np.nan if (get_is_none(x) == True) else x)
    default_list = [cal_field]
    df_time_tmp = df_tmp[dt_dict[dt]]
    if df_time_tmp.empty:
        df_time_tmp = pd.DataFrame(columns=default_list)
    df_con_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt] & condition_dict_all[con_key]]
    df_con_tmp = df_con_tmp[pd.isnull(df_con_tmp[cal_field]) == False]
    if df_con_tmp.empty:
        df_con_tmp = pd.DataFrame(columns=default_list)
    if cal_type == 'Cnt':
        re_value = df_con_tmp[cal_field].count()
        if df_con_tmp.empty:
            re_value = -999999
    elif cal_type == 'DistinctCnt':
        re_value = df_con_tmp[cal_field].nunique()
        if df_con_tmp.empty:
            re_value = -999999
    elif cal_type == 'RepeatCnt':
        unique_cnt = df_con_tmp[cal_field].nunique()
        _cnt = df_con_tmp[cal_field].count()
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = _cnt - unique_cnt
    elif cal_type == 'Std':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].std(), 2)
    elif cal_type == 'Avg':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].mean(), 2)
    elif cal_type == 'Max':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].max(), 2)
    elif cal_type == 'Min':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].min(), 2)
    elif cal_type == 'Sum':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].sum(), 2)
    elif cal_type == 'Pct':
        df_dem_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].count()
        num = df_con_tmp[cal_field].count()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, dem)
    elif cal_type == 'PctV2':
        df_dem_tmp = df_tmp[condition_dict_all[con_key] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].count()
        num = df_con_tmp[cal_field].count()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, dem)
    elif cal_type == 'DistinctPct':
        dem = df_con_tmp[cal_field].count()
        num = df_con_tmp[cal_field].nunique()
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, dem)
    elif cal_type == 'NuniquePct':
        df_dem_tmp = df_tmp[condition_dict_all[con] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].nunique()
        num = df_con_tmp[cal_field].nunique()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, dem)
    elif cal_type == 'NuniquePctV2':
        df_dem_tmp = df_tmp[condition_dict_all[con_key] & dt_dict[dt]]
        dem = df_dem_tmp[cal_field].nunique()
        num = df_con_tmp[cal_field].nunique()
        if df_dem_tmp.empty:
            dem = -999999
        if df_con_tmp.empty:
            num = -999999
        if df_dem_tmp.empty and df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, dem)
    elif cal_type == 'RepeatPct':
        cnt_dem = df_con_tmp[cal_field].count()
        unique_cnt_num = df_con_tmp[cal_field].nunique()
        num = cnt_dem - unique_cnt_num
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = get_cal_division(num, cnt_dem)
    elif cal_type == 'Median':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].median(), 2)
    elif cal_type == 'Skew':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].skew(), 2)
    elif cal_type == 'Mad':
        if df_con_tmp.empty:
            re_value = -999999
        else:
            re_value = round(df_con_tmp[cal_field].mad(), 2)
    else:
        re_value = -999999
    if str(re_value).lower().strip() in ['nan']:
        re_value = -999999
    return re_value


def calculate_app_features(app_data):
    """
    计算app特征集
    :param phone_sub:
    :param ApplyNO:
    :return:
    """
    try:
        if app_data.empty:
            return {
                # 新客模型第四版
                'appAllbad1InstallIntervalInstallIntervalMax60D': -999999,
                'appAllFuzzyLoanInstallIntervalInstallIntervalMedian60D': -999999,
                'appAllAllInstallIntervalAppNameCnt30D': -999999,
                'appAllgood1InstallIntervalInstallIntervalStdAllD': -999999,
                'appIsSystemgood1InstallIntervalInstallIntervalMedian60D': -999999,
                'appAllgood1InstallIntervalInstallIntervalMinAllD': -999999,
                'appAllAllInstallIntervalInstallIntervalMin3D': -999999,
                'appAllbad2InstallIntervalInstallIntervalMinAllD': -999999,
                'appAllbad1InstallIntervalInstallIntervalStdAllD': -999999,
                'appAllFuzzyLoanInstallIntervalInstallIntervalMedianAllD': -999999,
                'appIsSystembad2InstallIntervalInstallIntervalStdAllD': -999999,
                'appAllFuzzyLoanInstallIntervalInstallIntervalMedian30D': -999999,
                'appAllbad2InstallIntervalInstallIntervalStd60D': -999999,
                'appIsSystemFuzzyLoanInstallIntervalInstallIntervalStd60D': -999999,
            }

        df_tmp1 = app_data.copy()
        # 筛选符合条件的数据
        con_field_list = ['All', 'IsSystem', 'bad1', 'FuzzyLoan', 'good1', 'bad2']
        condition_dict_all = {}
        df_tmp1['All'] = 1
        for con in con_field_list:
            if con in ['All']:
                index = df_tmp1.All.ge(1)
            elif con in ['IsSystem']:
                index = df_tmp1.IsSystem.eq(1)
            elif con in ['IsNoSystem']:
                index = df_tmp1.IsSystem.eq(0)
            else:
                index = df_tmp1.conLabel.apply(lambda x: con in x)
            condition_dict_all[con] = index
        # 时间条件
        dt_install_dict = {}
        dt_list = ['All', 1, 3, 7, 14, 30, 60]
        for dt in dt_list:
            if dt in ['All']:
                index = df_tmp1.All.ge(1)
                dt_install_dict[dt] = index
            else:
                index_all = df_tmp1.InstallInterval.ge(0)
                index = df_tmp1.InstallInterval.le(dt * 24 * 3600)
                dt_install_dict[dt] = index & index_all

        # 特征的计算逻辑
        appAllbad1InstallIntervalInstallIntervalMax60D = get_windows_aggregation_main(df_tmp1, 'All', 60,
                                                                                      'bad1',
                                                                                      'InstallInterval',
                                                                                      'Max',
                                                                                      condition_dict_all,
                                                                                      dt_install_dict)
        appAllFuzzyLoanInstallIntervalInstallIntervalMedian60D = get_windows_aggregation_main(df_tmp1, 'All', 60,
                                                                                              'FuzzyLoan',
                                                                                              'InstallInterval',
                                                                                              'Median',
                                                                                              condition_dict_all,
                                                                                              dt_install_dict)
        appAllAllInstallIntervalAppNameCnt30D = get_windows_aggregation_main(df_tmp1, 'All', 30,
                                                                             'All',
                                                                             'AppName',
                                                                             'Cnt',
                                                                             condition_dict_all,
                                                                             dt_install_dict)

        appAllgood1InstallIntervalInstallIntervalStdAllD = get_windows_aggregation_main(df_tmp1, 'All', 'All',
                                                                                        'good1',
                                                                                        'InstallInterval',
                                                                                        'Std',
                                                                                        condition_dict_all,
                                                                                        dt_install_dict)
        appIsSystemgood1InstallIntervalInstallIntervalMedian60D = get_windows_aggregation_main(df_tmp1, 'IsSystem', 60,
                                                                                               'good1',
                                                                                               'InstallInterval',
                                                                                               'Median',
                                                                                               condition_dict_all,
                                                                                               dt_install_dict)
        appAllgood1InstallIntervalInstallIntervalMinAllD = get_windows_aggregation_main(df_tmp1, 'All', 'All',
                                                                                        'good1',
                                                                                        'InstallInterval',
                                                                                        'Min',
                                                                                        condition_dict_all,
                                                                                        dt_install_dict)
        appAllAllInstallIntervalInstallIntervalMin3D = get_windows_aggregation_main(df_tmp1, 'All', 3,
                                                                                    'All',
                                                                                    'InstallInterval',
                                                                                    'Min',
                                                                                    condition_dict_all,
                                                                                    dt_install_dict)
        appAllbad2InstallIntervalInstallIntervalMinAllD = get_windows_aggregation_main(df_tmp1, 'All', 'All',
                                                                                       'bad2',
                                                                                       'InstallInterval',
                                                                                       'Min',
                                                                                       condition_dict_all,
                                                                                       dt_install_dict)
        appAllbad1InstallIntervalInstallIntervalStdAllD = get_windows_aggregation_main(df_tmp1, 'All', 'All',
                                                                                       'bad1',
                                                                                       'InstallInterval',
                                                                                       'Std',
                                                                                       condition_dict_all,
                                                                                       dt_install_dict)
        appAllFuzzyLoanInstallIntervalInstallIntervalMedianAllD = get_windows_aggregation_main(df_tmp1, 'All', 'All',
                                                                                               'FuzzyLoan',
                                                                                               'InstallInterval',
                                                                                               'Median',
                                                                                               condition_dict_all,
                                                                                               dt_install_dict)
        appIsSystembad2InstallIntervalInstallIntervalStdAllD = get_windows_aggregation_main(df_tmp1, 'IsSystem', 'All',
                                                                                            'bad2',
                                                                                            'InstallInterval',
                                                                                            'Std',
                                                                                            condition_dict_all,
                                                                                            dt_install_dict)
        appAllFuzzyLoanInstallIntervalInstallIntervalMedian30D = get_windows_aggregation_main(df_tmp1, 'All', 30,
                                                                                              'FuzzyLoan',
                                                                                              'InstallInterval',
                                                                                              'Median',
                                                                                              condition_dict_all,
                                                                                              dt_install_dict)
        appAllbad2InstallIntervalInstallIntervalStd60D = get_windows_aggregation_main(df_tmp1, 'All', 60,
                                                                                      'bad2',
                                                                                      'InstallInterval',
                                                                                      'Std',
                                                                                      condition_dict_all,
                                                                                      dt_install_dict)
        appIsSystemFuzzyLoanInstallIntervalInstallIntervalStd60D = get_windows_aggregation_main(df_tmp1, 'IsSystem', 60,
                                                                                                'FuzzyLoan',
                                                                                                'InstallInterval',
                                                                                                'Std',
                                                                                                condition_dict_all,
                                                                                                dt_install_dict)

        return {
            'appAllbad1InstallIntervalInstallIntervalMax60D': appAllbad1InstallIntervalInstallIntervalMax60D,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedian60D': appAllFuzzyLoanInstallIntervalInstallIntervalMedian60D,
            'appAllAllInstallIntervalAppNameCnt30D': appAllAllInstallIntervalAppNameCnt30D,
            'appAllgood1InstallIntervalInstallIntervalStdAllD': appAllgood1InstallIntervalInstallIntervalStdAllD,
            'appIsSystemgood1InstallIntervalInstallIntervalMedian60D': appIsSystemgood1InstallIntervalInstallIntervalMedian60D,
            'appAllgood1InstallIntervalInstallIntervalMinAllD': appAllgood1InstallIntervalInstallIntervalMinAllD,
            'appAllAllInstallIntervalInstallIntervalMin3D': appAllAllInstallIntervalInstallIntervalMin3D,
            'appAllbad2InstallIntervalInstallIntervalMinAllD': appAllbad2InstallIntervalInstallIntervalMinAllD,
            'appAllbad1InstallIntervalInstallIntervalStdAllD': appAllbad1InstallIntervalInstallIntervalStdAllD,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedianAllD': appAllFuzzyLoanInstallIntervalInstallIntervalMedianAllD,
            'appIsSystembad2InstallIntervalInstallIntervalStdAllD': appIsSystembad2InstallIntervalInstallIntervalStdAllD,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedian30D': appAllFuzzyLoanInstallIntervalInstallIntervalMedian30D,
            'appAllbad2InstallIntervalInstallIntervalStd60D': appAllbad2InstallIntervalInstallIntervalStd60D,
            'appIsSystemFuzzyLoanInstallIntervalInstallIntervalStd60D': appIsSystemFuzzyLoanInstallIntervalInstallIntervalStd60D,
        }
    except Exception as e:
        # utils.get_logger().error(e)
        print(f"错误信息: {str(e)}")
        return {
            # 新客模型第四版
            'appAllbad1InstallIntervalInstallIntervalMax60D': -999976,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedian60D': -999976,
            'appAllAllInstallIntervalAppNameCnt30D': -999976,
            'appAllgood1InstallIntervalInstallIntervalStdAllD': -999976,
            'appIsSystemgood1InstallIntervalInstallIntervalMedian60D': -999976,
            'appAllgood1InstallIntervalInstallIntervalMinAllD': -999976,
            'appAllAllInstallIntervalInstallIntervalMin3D': -999976,
            'appAllbad2InstallIntervalInstallIntervalMinAllD': -999976,
            'appAllbad1InstallIntervalInstallIntervalStdAllD': -999976,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedianAllD': -999976,
            'appIsSystembad2InstallIntervalInstallIntervalStdAllD': -999976,
            'appAllFuzzyLoanInstallIntervalInstallIntervalMedian30D': -999976,
            'appAllbad2InstallIntervalInstallIntervalStd60D': -999976,
            'appIsSystemFuzzyLoanInstallIntervalInstallIntervalStd60D': -999976,

        }


def get_free_app_features(df):
    """
    获取sms数据集和计算sms特征集
    :param phone_sub:
    :param ApplyNO:
    :return:
    """
    app_data = get_format_data(df)
    app_features = calculate_app_features(app_data)
    return app_features


if __name__ == '__main__':
    ApplyNO = '171292318475053531'
    applist_features = get_app_df(ApplyNO)

    # applist_features = get_free_app_features(ApplyNO)
    print(applist_features)
